/****************************************************************************
 *
 *  ALi (Shanghai) Corporation, All Rights Reserved. 2003 Copyright (C)
 *
 *  File: power.c
 *
 *  Description: Routine for power off.
 *
 *  History:
 *      Date        Author      Version  Comment
 *      ====        ======      =======  =======
 *  1.  2003.5.1    Liu Lan     0.1.000  Initial 
 *
 ****************************************************************************/

#include <sys_config.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <hld/pan/pan_key.h>
#include <hld/pan/pan_dev.h>
#include <osal/osal.h>
#include <hal/hal_gpio.h>
#include <hld/dis/vpo.h>
#include <hld/deca/deca_dev.h>
#include <hld/pan/pan.h>
#include <api/libdiseqc/lib_diseqc.h>
#include <hld/sto/sto_dev.h>
#ifndef NEW_DEMO_FRAME
#include <api/libpub29/lib_hde.h>
#include <api/libpub29/lib_pub27.h>
#else
#include <api/libpub/lib_hde.h>
#endif
#include <api/libmp/media_player_api.h>

#ifdef USB_SUPPORT_HUB
#include <bus/usb2/usb.h>
#endif
#include <bus/dog/dog.h>

#include "win_com.h"
#include "key.h"
#include "control.h"
#include "vkey.h"
//#include "gpio_cfg.h"
#include "win_com_popup.h"

#ifdef HDTV_SUPPORT
#include <bus/hdmi/m36/hdmi_dev.h>
#include <bus/hdmi/m36/hdmi_api.h>
#endif
#ifdef SUPPORT_FRANCE_HD
#include "nit_info.h"
#include <api/libsi/si_nit.h>
#endif

#ifdef MULTI_CAS
#include <hld/smc/smc.h>
#endif
#ifdef SUPPORT_VMX
#include "vmx_ap/Osm.h"
#endif

#include "platform/board.h"

#include <bus/rtc/rtc.h>
#define POW_PRINTF(...)  do{}while(0)//libc_printf

extern UINT8   led_display_flag;

#ifdef USB_MP_SUPPORT
extern sys_state_t      system_state;
#endif

#define USB_CTL_POWER_DOWN	0
#define USB_CTL_SLEEP		1
#define USB_CTL_WAKEUP		2

void usb_power_control(int mode)
{
#ifdef USB_SUPPORT_HUB
    int i;
    for (i = 0; i < MAX_HANDLE_NUM; i++)
    {
		if (mode == USB_CTL_POWER_DOWN)
            usbd_power_down(i);
    }
#endif
}

void storage_power_down()
{
#ifndef DISABLE_USB  //3281 32m maybe don't have the usb hub.
    usb_power_control(USB_CTL_POWER_DOWN);
#endif
}

BOOL power_off_process(BOOL ota_scan)
{
	struct  YCbCrColor bgcolor;
	extern struct rfm_device*   g_rfm_dev;
	extern struct scart_device* g_scart_dev;
	UINT8 back_saved;

#if 1//ChengYu@20131105, LED pattern
	key_pan_display("OFF ", 4);
#endif

// Power HDMI phy at standby mode.
#ifdef HDTV_SUPPORT
	struct hdmi_device *hdmi_dev;
	hdmi_dev = (struct hdmi_device *)dev_get_by_id(HLD_DEV_TYPE_HDMI, 0);
	if (hdmi_dev != NULL)
	{
		if (SUCCESS != hdmi_dev->close(hdmi_dev))
		{
			PRINTF("hdmi_close failed!!\n");
			ASSERT(0);
		}
	}
#endif

#if defined(SUPPORT_TUN_AV2012) || defined(SUPPORT_TUN_MXL603) || defined(SUPPORT_TUN_MXL5007)
	//add by bill 2.12.02.21
	struct nim_device* nim_dev;
     //add by bill 2.12.02.21
     if(cur_tuner_idx == 0)
	   nim_dev = g_nim_dev;
      else
	   nim_dev = g_nim_dev2;	

      if(NULL != nim_dev->do_ioctl)
      {
      		nim_dev->do_ioctl(nim_dev, NIM_TURNER_SET_STANDBY, TRUE);
      }
#endif	
#ifdef CI_SUPPORT
	api_ci_unregister(NULL);
#endif

#ifdef DVR_PVR_SUPPORT
	api_pvr_clear_up_all();
#endif	

#ifdef USB_MP_SUPPORT
	if(system_state == SYS_STATE_USB_MP)
	{
		ap_udisk_close();
		
	}
#endif
    if(OSD_GetTaskVscrBuffer(osal_task_get_current_id()) == NULL)
    {
        BYTE *buffer;
        buffer = (BYTE *)MALLOC(600*1024);
        OSD_TaskBuffer_Init(osal_task_get_current_id(),buffer);
    }
#ifdef _INVW_JUICE
	INVIEW_pause(); /* I think we can live without the "Please wait.." popup */
#else
	win_compopup_init(WIN_POPUP_TYPE_SMSG); 					   
	win_compopup_set_msg_ext("Please wait...", NULL, 0);
	win_compopup_open_ext(&back_saved);
#endif
#ifndef _BUILD_OTA_E_
#ifndef DISABLE_USB
	storage_power_down(); // USB power down process
	usbd_detach_ex();
#endif    
#endif
#ifdef _INVW_JUICE
#else
	win_compopup_smsg_restoreback();
#endif
    // SE: Mute before scart power off to avoid noise
    api_audio_set_mute(TRUE);

	api_Scart_TVSAT_Switch(0);
	api_Scart_RGB_OnOff(0); //CVBS mode
	#ifdef _S3281_
	api_Scart_Power_OnOff(0);
	#else
	api_Scart_Power_OnOff(1);
	#endif
	
#ifdef VDAC_USE_SVIDEO_TYPE
	api_Svideo_OnOff(0);
#endif

#ifndef NEW_DEMO_FRAME
	if(hde_get_mode() != VIEW_MODE_MULTI)
	    UIChChgStopProg(TRUE);    
#endif

#if	(TTX_ON == 1)
	ttx_enable(FALSE);
#endif
#if (SUBTITLE_ON == 1)
	subt_enable(FALSE);
#endif
#if (ISDBT_CC==1)
	isdbtcc_enable(FALSE);
#endif

	OSD_ShowOnOff(OSDDRV_OFF);

	vpo_win_onoff(g_vpo_dev, FALSE);
#if defined(DUAL_VIDEO_OUTPUT) || defined(DUAL_VIDEO_OUTPUT_USE_VCAP)
	if(g_sd_vpo_dev != NULL)
		vpo_win_onoff(g_sd_vpo_dev,FALSE);
#endif
	bgcolor.uY = 16;
	bgcolor.uCb = 128;
	bgcolor.uCr = 128;		
	vpo_ioctl(g_vpo_dev,VPO_IO_SET_BG_COLOR,(UINT32)&bgcolor);
	deca_stop(g_deca_dev,0,ADEC_STOP_IMM);
	deca_close(g_deca_dev);
	vdec_close(g_decv_dev);
	vpo_close(g_vpo_dev);
#if defined(DUAL_VIDEO_OUTPUT) || defined(DUAL_VIDEO_OUTPUT_USE_VCAP)
	if(RET_SUCCESS!=vpo_close((struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1)))
		ASSERT(0);
#endif
	snd_stop(g_snd_dev);
//**********************************//add for Auto OTA

#if !defined(_BUILD_OTA_E_) && defined(AUTO_OTA)
#if(defined(DVBT_SUPPORT)||defined(ISDBT_SUPPORT)||defined(DVBC_SUPPORT))
	if(ota_scan)
	{
		key_pan_display("srch", 4);
		date_time et;
		BOOL flag_et = api_ota_get_recently_timer(&et);
		BOOL bootup = FALSE;
		#ifdef NEW_MANUAL_OTA 
		extern BOOL ota_set_menu;
		ota_set_menu = FALSE;
		#endif
		bootup = ota_stby_search(&et);

		if(bootup)
		{
			get_local_time(&et);
			flag_et = TRUE;
			return FALSE;
		}
	}	
#endif
#endif

//***********************************//add end

//api_Scart_OutPut_Switch(0);
	SetLNBShortDetect(0);
	Set12VShortDetect(0);
    board_lnb_power(0, 0);
    board_lnb_power(1, 0);
	board_antenna_power(0, 0);                        
    board_antenna_power(1, 0);                         
	//api_LNB_power(0);
	
#if(SYS_12V_SWITCH == SYS_FUNC_ON)
	 api_diseqc_set_12v(g_nim_dev, 0);
#endif    

	sie_close();

#ifdef NEW_DEMO_FRAME
	sim_close_monitor(0);
#else
	si_monitor_off(0xFFFFFFFF);
#endif
	stop_tdt();
//reduce the space for ota
#ifndef _BUILD_OTA_E_
	epg_off();
#endif

	dm_set_onoff(0);

	//close drivers	
	dmx_stop( g_dmx_dev);
	dmx_close( g_dmx_dev);
    if (g_dmx_dev2)
    {
    	dmx_stop(g_dmx_dev2);
	    dmx_close(g_dmx_dev2);
    }
    
    snd_close(g_snd_dev);
	
    api_Scart_OutPut_Switch(0); // put it after snd_close() to avoid noise by Kwunleung Zhou

	nim_close(g_nim_dev);
	if(g_nim_dev2)
		nim_close(g_nim_dev2);
	if(g_rfm_dev)
		rfm_close(g_rfm_dev);
	led_display_flag = 0;

#ifdef MULTI_CAS
    struct smc_device *smc_dev = NULL;
	UINT8 i;
    for(i=0;i<2;i++)
    {
        smc_dev = (struct smc_device *)dev_get_by_id(HLD_DEV_TYPE_SMC, i);
        if(smc_dev!=NULL)
        {
            smc_close(smc_dev);
        }
    }
#endif
	return TRUE;
}

void power_off_process2(void)
{
    BoardCfg* cfg = get_board_cfg();
    if(sys_ic_get_chip_id() != ALI_S3281)
        chip_gpio_set(cfg->sys_power, 0);  // power off
    
    // SE: Cancel Mute before entering standby to avoid power leak
    api_audio_set_mute(FALSE);

    chip_ci_power(FALSE);
}

void power_on_process(void)
{
	date_time dt;	//ctchen
	SYSTEM_DATA* sys_data;
	UINT32 tmp;
	
	sys_data = sys_data_get();

	key_pan_display(" on ", 4);

	pan_close(g_pan_dev);

	 if(sys_data->local_time.buseGMT)
	    get_STC_time(&sys_data->sys_dt);
	else
        get_local_time(&sys_data->sys_dt);	//ctchen

    sys_data->bstandmode = 0;
	sys_data_save(1);
	
	dog_m3327e_attach(1);
	osal_interrupt_disable(); //before enter watchdog_reboot,you MUST NOT read/write flash as soon as possible.make sure the bus is clear.
	*((volatile UINT32 *)0xb802e098)=0xc2000d03;
	tmp = *((volatile UINT32 *)0xb802e098);
	dog_mode_set(0, DOG_MODE_WATCHDOG, 10, NULL);
	while(1);
}

void api_standby_led_onoff(BOOL onoff)
{
	board_standby_led_onoff(onoff);
}

void power_switch(UINT32 mode)
{
    unsigned long keycode;
    SYSTEM_DATA* sys_data;
	UINT32 vkey;
	UINT32 times = 0,display_type=0;
	date_time dt,dt_bak;
	UINT32 hh,mm,ss;
	char time_str[10];
	struct pan_key key_struct;
    UINT32 timer;
    struct sto_device *dev = (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0);
#ifdef SUPPORT_VMX
	api_check_osm_triggers(OSM_POWER_DOWN);
#endif
#ifdef SUPPORT_FRANCE_HD
	struct nit_section_info *nit_info;
	struct NIT_VER_INFO *nit_ver_info = NULL;
	UINT8 i;
	
	#ifndef _BUILD_OTA_E_    
    //make sure USB command is complete
    int i=0;
    usb_inhibit_rw(1);    
    for(i=0;i<1000;i+=10)
    {
        osal_task_sleep(10);
        if(TRUE == usb_rw_completed())
        {
            break;
        }
    }    
    force_usb_suspend();
#endif    
	

	nit_info = MALLOC(sizeof(struct nit_section_info));
	load_nit_monitor_info(nit_info);
	nit_ver_info = MALLOC(sizeof(struct NIT_VER_INFO)+sizeof(struct NIT_SER_INFO)*(nit_info->s_nr-1));
	MEMSET(nit_ver_info, 0, sizeof(struct NIT_VER_INFO)+sizeof(struct NIT_SER_INFO)*(nit_info->s_nr-1));
	nit_ver_info->num = nit_info->s_nr;
	nit_ver_info->verison_number = nit_info->version_num;
	for(i=0; i<nit_info->s_nr; i++)
	{
		nit_ver_info->nit_service[i].sid = nit_info->s_info[i].sid;
		nit_ver_info->nit_service[i].tsid = nit_info->s_info[i].tsid;
		nit_ver_info->nit_service[i].onid = nit_info->s_info[i].onid;
	}
	save_nit_data(nit_ver_info, sizeof(struct NIT_VER_INFO)+sizeof(struct NIT_SER_INFO)*(nit_ver_info->num-1));
	FREE(nit_ver_info);
	FREE(nit_info);
#endif

    #ifdef  SUPPORT_CAS9
	    clean_mmi_msg(5,1);
    #endif
	sys_data = sys_data_get(); 
	sys_data->bstandmode = 1;
	sys_data_save(1);

#ifndef _BUILD_OTA_E_
#ifdef MEDIA_PLAYER_VIDEO_SUPPORT
    if(system_state == SYS_STATE_USB_MP)
		mpg_cmd_stop_proc();
#endif
#endif
	system_state = SYS_STATE_POWER_OFF;

//Power off USB
    board_usb_power(FALSE);

	
	#ifdef AUTO_OTA
	api_stop_play(0);
	if(!power_off_process(1))
	{
        power_on_process();
        return;
	}
	#else
	power_off_process(0);
	#endif
    power_off_process2();
//in "power_off_process()" call api_stop_record(), the function may change database
//so save data again here
	sys_data_save(1);
/* Marked by ChengYu@20131105, LED pattern, already display "OFF" in power_off_process
#ifdef DDR_POWER_CONTROL_ENABLE
    // enable DDR power control gpio
    //GPIO_enable_pos(DDR_POWER_CTL_GPIO_POS, TRUE);
    if(mode != 1)
		key_pan_display("    ", 4);
#else
    if(mode != 1)
		key_pan_display("oFF ", 4);
#endif
*/
	key_pan_display_standby(1);
	key_pan_display_lock(0);
#ifdef SHOW_TWO_TUNER_LOCK_STATUS	
	key_pan_display_lock2(0);
#endif

    api_standby_led_onoff(TRUE);
    board_power(FALSE);
	//GPIO_power_onoff(FALSE);
/*
#ifdef PMU_ENABLE
        pmu_m36_en();
#endif 
*/
	if(1)	/* Real Standby*/
	{
		UINT32	cur_time, target_time;

		get_local_time(&dt);
		get_STC_time(&dt_bak);
		pan_close(g_pan_dev);
        timer = api_get_recently_timer();
		// disable interrupt
		osal_interrupt_disable();

		cur_time = (dt.sec & 0x3F ) | ((dt.min & 0x3F )<<6)  | ((dt.hour & 0x1F )<<12) | ((dt.day & 0x1F)<<17)
			| ((dt.month & 0xF) << 22) | (((dt.year % 100) & 0x3F)<<26);
if((ALI_S3811==sys_ic_get_chip_id()) && (sys_ic_get_rev_id() >= IC_REV_1))
{
    #ifdef PMU_ENABLE
    struct rtc_time base_time={0,0,0,0,0,0,0};
			INT32 o_h=0,o_m=0,o_s=0;
			get_STC_offset(&o_h,&o_m,&o_s);
			base_time.year = dt_bak.year%4;
			base_time.month = dt_bak.month;
			base_time.date =dt_bak.day;
			base_time.hour  = dt_bak.hour;
			base_time.min = dt_bak.min;
	        base_time.sec =dt_bak.sec ;
    rtc_s3811_set_value(&base_time)  ;//set current time
    SYSTEM_DATA *system_data_year;
    system_data_year=sys_data_get();
    system_data_year->sys_dt.year=dt.year;
    
    sys_data_save(1);
	#endif
#ifdef PMU_ENABLE
       #ifdef PMU_POWERSTANDBY_CLOSE
         pmu_m36_powerstandby_close();
       #else
         pmu_m36_en();
       #endif      
#endif 
}
if((ALI_S3811==sys_ic_get_chip_id()) && (sys_ic_get_rev_id() == IC_REV_0))
{
    #ifdef PMU_ENABLE
        pmu_m36_en();
    #endif 
}

#ifdef WATCH_DOG_SUPPORT
        dog_stop(0);
#endif
		sto_io_control(dev, STO_DRIVER_SUSPEND,0);	 
		sys_ic_enter_standby(timer, cur_time);
		// enable interrupt
		osal_interrupt_enable();
	}	
    
     
    while (1)
    {
		times++;
		times = times % 100; 
		osal_delay(5000);
    				
		if(times==0)
		{
			//get_cur_time(&hh,&mm,&ss);
			get_local_time(&dt);
			hh = dt.hour;
			mm = dt.min;

			if(display_type==0)
			    sprintf(time_str,"%02d%02d ",hh,mm);
			else
				sprintf(time_str,"%02d.%02d",hh,mm);

			key_pan_display(time_str, 5);
			display_type++;
			display_type %= 2;
		}
		
		vkey = V_KEY_NULL;
		if(key_get_key(&key_struct,0))
		{
			keycode = scan_code_to_msg_code(&key_struct);
			ap_hk_to_vk(0, keycode, &vkey);
		}
		else
			keycode = PAN_KEY_INVALID;
		if(vkey == V_KEY_POWER)
		{
			power_on_process();
		}
	}
}

